﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Data.SqlClient;

/*=====================================================================
  This file is part of a Microsoft SQL Server Shared Source Application.
  Copyright (C) Microsoft Corporation.  All rights reserved.
 
THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
======================================================= */


namespace Microsoft.SqlCommunity.FaultRetry
{

    /// <summary>
    /// This dialog is used to set the name of the principal and mirror servers for the application.
    /// The dialog is slightly clever in that it tries to save server names you have used before in 
    /// isolated storage so that you normally would only have to type the server names once.
    /// </summary>
    public partial class ConfigureDialog : Window, IServerListsSource
    {
        public ServerSets AllServers { get; set; }  // The set of all known server pairs.

        public ServerSet CurrentServers { get; set; } //  The currently selected Primary/Mirror pair.

        private string _databaseException = null;
        public string DatabaseException
        {
            get { return _databaseException; }
            set { _databaseException = value; }
        }

        /// <summary>
        /// This is true if the user has entered reasonably correct and complete information in the dialog.
        /// </summary>
        private bool IsConfigureDialogContentValid
        {
            get
            {
                if (PrincipalComboBox.Text.Length == 0 || MirrorComboBox.Text.Length == 0)
                {
                    ShowError("Both the principal and mirror servers must be specified.");
                    return false;
                }
                if (PrincipalComboBox.Text.Equals(MirrorComboBox.Text, StringComparison.InvariantCultureIgnoreCase))
                {
                    ShowError("The principal and mirror servers must be different.");
                    return false;
                }
                return true;
            }
        }

        /// <summary>
        /// Provide feedback to the user if they make a mistake.
        /// </summary>
        /// <param name="message">Hopefully something useful to tell the user about the mistake they've made</param>
        private void ShowError(string message)
        {
            ErrorLabel.Content = message;
            ErrorLabel.Visibility = Visibility.Visible;
        }

        /// <summary>
        /// An event which is raised if the user changes the currently selected servers and/or added new servers.  The 
        /// data access layer uses this event to ensure changes get persisted.
        /// </summary>
        public event EventHandler<EventArgs> ServerListsChanged;

        /// <summary>
        /// Initialize this dialog
        /// </summary>
        public ConfigureDialog()
        {
            CurrentServers = null;
            // Attempt to get a list of previously specified server names from isolated storage.
            DataAccess.Current.InitializeServerLists(this);

            InitializeComponent();

            // If we are successful at getting some servers, select the first pair.
            if (AllServers.Count > 0)
            {
                PrincipalComboBox.SelectedIndex = 0;
                MirrorComboBox.SelectedIndex = 0;
            }

        }

        /// <summary>
        /// Invoked when the user clicks on the Cancel button.
        /// Allow the user to abort if they don't want to configure the server names at this time.
        /// </summary>
        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

        /// <summary>
        /// Invoked when the user clicks on the OK button.  Allows the user to indicate which servers they want to use.
        /// </summary>
        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            // If the user did a reasonable job at naming servers, update the current principal/mirror server pair with that they
            // selected.
            if (IsConfigureDialogContentValid)
            {
                try
                {
                    CurrentServers = new ServerSet(PrincipalComboBox.Text, MirrorComboBox.Text);
                    //Maintain a history of the servers the user has named. 
                    MaybeUpdateServerLists();
                    //Indicate success to the caller!
                    DialogResult = true;
                }
                catch (SqlException se)
                {
                    _databaseException = se.Message;
                    CurrentServers = null;
                    DialogResult = false;
                }
            }
        }

        /// <summary>
        /// Returns true if servers were picked.
        /// </summary>
        public bool AreServersSelected 
        {
            get
            {
                return CurrentServers != null;
            }
        }

        /// <summary>
        /// If the history of servers selected list (AllServers) has changed, then update the list, and raise an event which 
        /// may be consumed by the data access layer in order to persist the history across application invocation.
        /// </summary>
        internal void MaybeUpdateServerLists()
        {
            //The goal is to make sure we keep track of all servers the user has specified (segregated into
            //principal and server lists), and also keep the most recently used set of servers at the front
            //of the list.
                    
            // If we have a set of current server names and either there are no servers in the list of all servers
            // or we're not at the front, update the list of all servers and raise the ServerListsChanged event.
            if (CurrentServers != null
                && (AllServers.Count == 0 || !AllServers[0].Equals(CurrentServers)))
            {
                AllServers.Remove(CurrentServers);
                AllServers.Insert(0, CurrentServers);
                if (ServerListsChanged != null)
                    ServerListsChanged(this, new EventArgs());
            }

        }

        /// <summary>
        /// If the user changes something then we can clear any outstanding errors.
        /// </summary>
        private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if ((e.AddedItems.Count > 0 && e.AddedItems[0] is ServerSet)
                || IsConfigureDialogContentValid) 
                ErrorLabel.Visibility = Visibility.Hidden;
        }

        /// <summary>
        /// Invoked when the user clicks on the Clear History button.
        /// Request that the data access layer delete history information about previously selected servers.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ClearHistoryButton_Click(object sender, RoutedEventArgs e)
        {
            AllServers.Clear();
            CurrentServers = null;
            DataAccess.Current.ClearServerLists();

        }
    }
}
